package com.ys.controller.web.bi;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bo.dto.NameValueDto;
import com.ys.entity.base.TpAmazonRegionItem;
import com.ys.entity.business.TpAmazonShop;
import com.ys.entity.hr.ThrOperateCompanyApply;
import com.ys.entity.shiro.LoginUser;
import com.ys.entity.sys.TbStaticConfig;
import com.ys.entity.sys.TsOperateOrg;
import com.ys.entity.sys.TsUserInfo;
import com.ys.enume.sys.YsRoleMenuEnum;
import com.ys.mapper.bi.BiMapper;
import com.ys.mapper.sys.SysMapper;
import com.ys.service.sys.ImgcodeService;
import com.ys.util.DateUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.R;

import lombok.AllArgsConstructor;
import lombok.Data;

@Controller
@RequestMapping("/web/bi")
public class WebBiController {

	public static Long MENU_ID = 10148L;

	@Autowired
	private ImgcodeService imgcodeService;
	@Autowired
	private BiMapper biMapper;
	@Resource
	private SysMapper sysMapper;

	/*
	 * BI首页
	 */
	@GetMapping("/index")
	public String index(Model model, String loginName, String pass){

		String loginUserId = ShiroUtils.getUserId();
		if (loginUserId == null || loginUserId.length() == 0) {
			if (loginName != null && loginName.length() > 0 && pass != null && pass.length() > 0) {

				TsUserInfo tsUserInfo = new TsUserInfo().setUserId(loginName).setUserPassWord(pass).queryFirst();
				if (tsUserInfo != null) {
					imgcodeService.doAuthAfterLogin(tsUserInfo);
				}
			} else {
				return "/login";
			}
		} else {
			if (loginName != null && loginName.length() > 0 && pass != null && pass.length() > 0 && !loginUserId.equals(loginName)) {

				TsUserInfo tsUserInfo = new TsUserInfo().setUserId(loginName).setUserPassWord(pass).queryFirst();
				if (tsUserInfo != null) {
					imgcodeService.doAuthAfterLogin(tsUserInfo);
				}
			}
		}
		
		return "bi/index";
	}

	/*
	 * 亚马逊
	 */
	@GetMapping("/amazon")
	public String amazon(Model model, String loginName, String pass){

		List<NameValueDto> regionArr = new ArrayList<NameValueDto>();
		List<TpAmazonRegionItem> listTpAmazonRegionItem = new TpAmazonRegionItem().queryList();
		for(TpAmazonRegionItem tpAmazonRegionItem : listTpAmazonRegionItem) {
			String name = tpAmazonRegionItem.getCountryName();
			String value = tpAmazonRegionItem.getMarketplaceId();
			regionArr.add(new NameValueDto(name, value));
		}
		IndexDto dto = new IndexDto(regionArr);
		model.addAttribute("dto", dto);
		return "bi/amazon";
	}
	@Data
	@AllArgsConstructor
	private static class IndexDto{
		private List<NameValueDto> regionArr;
	}


	/**
	 * 获取区域列表
	 */
	@PostMapping("/listRegion")
	@ResponseBody
	public R listRegion(){
		List<TpAmazonRegionItem> listTpAmazonRegionItem = new TpAmazonRegionItem().queryList();
		return R.ok(listTpAmazonRegionItem);
	}

	/**
	 * 获取店铺列表
	 */
	@PostMapping("/listShop")
	@ResponseBody
	public R listShop(
			String name,
			String region,
			String org,
			String company,
			String user,
			Integer pageNo){
		
		LoginUser loginUser = ShiroUtils.getLoginUser();

		String userId = loginUser.getUserId();
		Long roleId = loginUser.getRoleId();
		Integer authType = roleId.longValue() == 1L ? YsRoleMenuEnum.Type.ALL.value : sysMapper.getTypeOfRoleMenu(roleId, MENU_ID);
		
		System.out.println("authType---" + authType);

		pageNo = pageNo != null ? pageNo - 1 : 0;

		region = region != null && region.length() > 0 ? region : "[]";
		org = org != null && org.length() > 0 ? org : "[]";
		company = company != null && company.length() > 0 ? company : "[]";
		user = user != null && user.length() > 0 ? user : "[]";

		TpAmazonShop cond = new TpAmazonShop()
				.setFields("A.Id value,A.ShopName name")
				.setPage(pageNo)
				.setSize(50);
		if (name != null && name.length() > 0) {
			cond.where("A.ShopName like '%" + name + "%'");
		}

		cond.addLeftJoin("TP_AmazonSeller B ON B.id = A.AmazonSellerId")
			.addLeftJoin("THR_OperateCompanyApply C ON C.Vgsbm = B.Vgsbm");
		
		// 权限过滤
		if (authType == YsRoleMenuEnum.Type.USER.value) {
			cond.addLeftJoin("TS_UserChange AA ON AA.Id = C.OperatorChangeId")
					.where("AA.UserId = '" + userId + "'");
		} else if (authType == YsRoleMenuEnum.Type.OPERATOR.value) {
			cond.addLeftJoin("TS_OperateOrg BB ON BB.Id = C.OperateOrgId")
				.where("BB.NodeLft >= " + loginUser.getOperateOrgNodeLft())
				.where("BB.NodeRgt <= " + loginUser.getOperateOrgNodeRgt());
		} else if (authType == null) {
			cond.where("1=2");
		}

		// 过滤区域
		JSONArray regionJA = JSON.parseArray(region);
		if (regionJA.size() > 0) {
			String values = "'";
			for (int i = 0; i < regionJA.size(); i++) {
				JSONObject regionJO = regionJA.getJSONObject(i);
				values = values + regionJO.getString("value") + "','";
			}
			values = values.substring(0, values.length() - 2);
			cond.where("A.MarketplaceIds in (" + values + ")");
		}

		// 过滤运营机构
		JSONArray orgJA = JSON.parseArray(org);
		if (orgJA.size() > 0) {
			String values = "";
			for (int i = 0; i < orgJA.size(); i++) {
				JSONObject orgJO = orgJA.getJSONObject(i);
				values = values + orgJO.getString("value") + ",";
			}
			values = values.substring(0, values.length() - 1);
			cond.where("C.OperateOrgId in (" + values + ")");
		}

		// 过滤运营公司
		JSONArray companyJA = JSON.parseArray(company);
		if (companyJA.size() > 0) {
			String values = "'";
			for (int i = 0; i < companyJA.size(); i++) {
				JSONObject companyJO = companyJA.getJSONObject(i);
				values = values + companyJO.getString("value") + "','";
			}
			values = values.substring(0, values.length() - 2);
			cond.where("B.Vgsbm in (" + values + ")");
		}

		// 过滤运营人员
		JSONArray userJA = JSON.parseArray(user);
		if (userJA.size() > 0) {
			String values = "'";
			for (int i = 0; i < userJA.size(); i++) {
				JSONObject userJO = userJA.getJSONObject(i);
				values = values + userJO.getString("value") + "','";
			}
			values = values.substring(0, values.length() - 2);
			System.out.println("运营人员values" + values);
			cond.addLeftJoin("TS_UserChange AAA ON AAA.Id = C.OperatorChangeId")
				.where("AAA.UserId in (" + values + ")");
		}
		List<Map<String, Object>> list = cond.queryMap();

		Integer totalNum = cond.count();
		R r = R.ok(list);
		r.put("totalPage", (totalNum + 49) / 50 );
		return r;
	}

	/**
	 * 获取运营机构列表
	 */
	@PostMapping("/listOrg")
	@ResponseBody
	public R listOrg(String name){
		
		LoginUser loginUser = ShiroUtils.getLoginUser();
		Long roleId = loginUser.getRoleId();
		Integer authType = roleId.longValue() == 1L ? YsRoleMenuEnum.Type.ALL.value : sysMapper.getTypeOfRoleMenu(roleId, MENU_ID);
		
		TsOperateOrg cond = new TsOperateOrg().setFields("A.Id value,A.Name name");
		if (name != null && name.length() > 0) {
			cond.where("A.Name like '%" + name + "%'");
		}
		if (authType == YsRoleMenuEnum.Type.ALL.value) {
		} else if (authType == YsRoleMenuEnum.Type.OPERATOR.value || authType == YsRoleMenuEnum.Type.USER.value) {
			cond.where("A.NodeLft >= " + loginUser.getOperateOrgNodeLft());
			cond.where("A.NodeRgt <= " + loginUser.getOperateOrgNodeRgt());
		} else {
			cond.where("1=0");
		}
		
		List<Map<String, Object>> list = cond.queryMap();

		return R.ok(list);
	}

	/**
	 * 获取运营公司列表
	 */
	@PostMapping("/listOperateCompany")
	@ResponseBody
	public R listOperateCompany(
			String name,
			String region,
			String org,
			String company,
			String user){
		ThrOperateCompanyApply cond = new ThrOperateCompanyApply()
				//.setEffectStock(1)
				.setFields("A.VGsBm value,A.VGsJc name");
		if (name != null && name.length() > 0) {
			cond.where("A.VGsJc like '%" + name + "%'");
		}
		List<Map<String, Object>> list = cond.queryMap();

		return R.ok(list);
	}

	/**
	 * 获取运营人员列表
	 */
	@PostMapping("/listOperateUser")
	@ResponseBody
	public R listOperateUser(String name){
		ThrOperateCompanyApply cond = new ThrOperateCompanyApply()
				//.setEffectStock(1)
				.setFields("DISTINCT A.CUser value,A.CUserName name")
				.where("A.CUser is not null")
				.where("A.CUser != ''")
				.setOrderby("A.CUser ASC");
		if (name != null && name.length() > 0) {
			cond.where("A.CUserName like '%" + name + "%'");
		}
		List<Map<String, Object>> list = cond.queryMap();

		return R.ok(list);
	}

	/**
	 * 店铺销售
	 */
	@PostMapping("/dpxx")
	@ResponseBody
	public R dpxx(
			String region,
			String org,
			String company,
			String user,
			String shop,
			Integer timeType){
		
		LoginUser loginUser = ShiroUtils.getLoginUser();

		String userId = loginUser.getUserId();
		Long roleId = loginUser.getRoleId();
		Integer authType = roleId.longValue() == 1L ? YsRoleMenuEnum.Type.ALL.value : sysMapper.getTypeOfRoleMenu(roleId, MENU_ID);

		// 店铺筛选列表
		List<Long> listShop = getListShop(shop);

		TbStaticConfig tbStaticConfig = new TbStaticConfig().setKeyOne("refresh-amazon-shop-order").setKeyTwo("finishi-time").queryFirst();
		String finishTime = tbStaticConfig.getName();

		Date now = new Date();
		String dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		String dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		if (timeType == 1) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -30));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		}

		Map<String, Object> dataMapYesterday = biMapper.getDPXX(timeType,dayBegin,dayEnd, listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		BigDecimal amountSaleYesterday = new BigDecimal(dataMapYesterday.get("AmountRmbTotal").toString());
		Integer numProductYesterday = Integer.parseInt(dataMapYesterday.get("NumProductTotal").toString());
		Integer numSaleYesterday = Integer.parseInt(dataMapYesterday.get("NumSaleTotal").toString());
		Integer numBackYesterday = Integer.parseInt(dataMapYesterday.get("NumBackTotal").toString());

		DpxxDto.DayDto yesterday = null;
		{
			String price = "¥" + amountSaleYesterday.toString();
			Integer numProduct = numProductYesterday;
			String priceAvg = "¥" + (numProductYesterday > 0 ? amountSaleYesterday.divide(new BigDecimal(numProductYesterday), 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO);
			Integer numOrder = numSaleYesterday;
			Integer numOrderBack = numBackYesterday;
			yesterday = new DpxxDto.DayDto(price, numProduct, priceAvg, numOrder, numOrderBack);
		}

		dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -2));
		dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -2));
		if (timeType == 1) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -60));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -31));
		}

		Map<String, Object> dataMapBefore = biMapper.getDPXX(timeType,dayBegin,dayEnd, listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		BigDecimal amountSaleBefore = new BigDecimal(dataMapBefore.get("AmountRmbTotal").toString());
		Integer numProductBefore = Integer.parseInt(dataMapBefore.get("NumProductTotal").toString());
		Integer numSaleBefore = Integer.parseInt(dataMapBefore.get("NumSaleTotal").toString());
		Integer numBackBefore = Integer.parseInt(dataMapBefore.get("NumBackTotal").toString());
		DpxxDto.DayDto before = null;
		{
			String price = "¥" + amountSaleBefore.toString();
			Integer numProduct = numProductBefore;
			String priceAvg = "¥" + (numProductBefore > 0 ? amountSaleBefore.divide(new BigDecimal(numProductBefore), 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO);
			Integer numOrder = numSaleBefore;
			Integer numOrderBack = numBackBefore;
			before = new DpxxDto.DayDto(price, numProduct, priceAvg, numOrder, numOrderBack);
		}

		DpxxDto.AddPercentDto addPercent = null;
		{
			BigDecimal pricePercent = amountSaleBefore.compareTo(BigDecimal.ZERO) > 0 ? amountSaleYesterday.subtract(amountSaleBefore).multiply(new BigDecimal(100)).divide(amountSaleBefore, 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String price = pricePercent + (pricePercent.compareTo(BigDecimal.ZERO) > 0 ? "%↑" : "%↓");

			BigDecimal numProductPercent = numProductBefore > 0 ? new BigDecimal(numProductYesterday - numProductBefore).multiply(new BigDecimal(100)).divide(new BigDecimal(numProductBefore), 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String numProduct = numProductPercent + (numProductPercent.compareTo(BigDecimal.ZERO) > 0 ? "%↑" : "%↓");

			BigDecimal priceAvgYesterday = new BigDecimal(yesterday.getPriceAvg().replace("¥", ""));
			BigDecimal priceAvgBefore = new BigDecimal(before.getPriceAvg().replace("¥", ""));
			BigDecimal priceAvgPercent = priceAvgBefore.compareTo(BigDecimal.ZERO) > 0 ? priceAvgYesterday.subtract(priceAvgBefore).multiply(new BigDecimal(100)).divide(priceAvgBefore, 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String priceAvg = priceAvgPercent + (priceAvgPercent.compareTo(BigDecimal.ZERO) > 0 ? "%↑" : "%↓");

			BigDecimal numOrderPercent = new BigDecimal(numSaleBefore).compareTo(BigDecimal.ZERO) > 0 ? new BigDecimal(numSaleYesterday - numSaleBefore).multiply(new BigDecimal(100)).divide(new BigDecimal(numSaleBefore), 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String numOrder = numOrderPercent + (numOrderPercent.compareTo(BigDecimal.ZERO) > 0 ? "%↑" : "%↓");

			BigDecimal numOrderBackPercent = new BigDecimal(numBackBefore).compareTo(BigDecimal.ZERO) > 0 ? new BigDecimal(numBackYesterday - numBackBefore).multiply(new BigDecimal(100)).divide(new BigDecimal(numBackBefore), 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String numOrderBack = numOrderBackPercent + (numOrderBackPercent.compareTo(BigDecimal.ZERO) > 0 ? "%↑" : "%↓");
			addPercent = new DpxxDto.AddPercentDto(price, numProduct, priceAvg, numOrder, numOrderBack);
		}
		DpxxDto dto = new DpxxDto(finishTime, yesterday, before, addPercent);
		return R.ok(dto);
	}
	@Data
	@AllArgsConstructor
	private static class DpxxDto{
		private String finishTime; // 更新截止时间
		private DayDto yesterday;
		private DayDto before;
		private AddPercentDto addPercent;

		@Data
		@AllArgsConstructor
		private static class DayDto{
			private String price; // 销售金额
			private Integer numProduct; // 销售数量
			private String priceAvg; // 平均售价
			private Integer numOrder; // 销售单量
			private Integer numOrderBack; // 弃退单量
		}

		@Data
		@AllArgsConstructor
		private static class AddPercentDto{
			private String price; // 销售金额
			private String numProduct; // 销售数量
			private String priceAvg; // 平均售价
			private String numOrder; // 销售单量
			private String numOrderBack; // 弃退单量
		}
	}

	/**
	 * 店铺广告
	 */
	@PostMapping("/dpgg")
	@ResponseBody
	public R dpgg(
			String region,
			String org,
			String company,
			String user,
			String shop,
			Integer timeType){
		
		LoginUser loginUser = ShiroUtils.getLoginUser();

		String userId = loginUser.getUserId();
		Long roleId = loginUser.getRoleId();
		Integer authType = roleId.longValue() == 1L ? YsRoleMenuEnum.Type.ALL.value : sysMapper.getTypeOfRoleMenu(roleId, MENU_ID);

		// 店铺筛选列表
		List<Long> listShop = getListShop(shop);

		TbStaticConfig tbStaticConfig = new TbStaticConfig().setKeyOne("refresh-amazon-advert").setKeyTwo("finishi-time").queryFirst();
		String finishTime = tbStaticConfig.getName();

		Date now = new Date();
		String dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		String dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		if (timeType == 1) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -30));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		}

		Map<String, Object> dataMapYesterday = biMapper.getDPGG(timeType,dayBegin,dayEnd, listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());

		dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -2));
		dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -2));
		if (timeType == 1) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -60));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -31));
		}

		Map<String, Object> dataMapBefore = biMapper.getDPGG(timeType,dayBegin,dayEnd, listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());

		BigDecimal spendYesterday = new BigDecimal(dataMapYesterday.get("SpendTotal").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
		BigDecimal sales1dYesterday = new BigDecimal(dataMapYesterday.get("Sales1dTotal").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
		Integer unitsSoldClicks1dYesterday = Integer.parseInt(dataMapYesterday.get("UnitsSoldClicks1dTotal").toString());
		Integer clicksYesterday = Integer.parseInt(dataMapYesterday.get("ClicksTotal").toString());

		DpggDto.DayDto yesterday = null;
		{
			String spend = "¥" + spendYesterday.toString();
			String sales1d = "¥" + sales1dYesterday.toString();
			Integer unitsSoldClicks1d = unitsSoldClicks1dYesterday;
			String cpc = "¥" + (clicksYesterday > 0 ? spendYesterday.divide(new BigDecimal(clicksYesterday), 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO);
			String acos = (sales1dYesterday.compareTo(BigDecimal.ZERO) > 0 ? spendYesterday.multiply(new BigDecimal(100)).divide(sales1dYesterday, 0, BigDecimal.ROUND_HALF_UP) : 0) + "%";
			yesterday = new DpggDto.DayDto(spend, sales1d, unitsSoldClicks1d, cpc, acos);
		}

		BigDecimal spendBefore = new BigDecimal(dataMapBefore.get("SpendTotal").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
		BigDecimal sales1dBefore = new BigDecimal(dataMapBefore.get("Sales1dTotal").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
		Integer unitsSoldClicks1dBefore = Integer.parseInt(dataMapBefore.get("UnitsSoldClicks1dTotal").toString());
		Integer clicksBefore = Integer.parseInt(dataMapBefore.get("ClicksTotal").toString());
		DpggDto.DayDto before = null;
		{
			String spend = "¥" + spendBefore.toString();
			String sales1d = "¥" + sales1dBefore.toString();
			Integer unitsSoldClicks1d = unitsSoldClicks1dBefore;
			String cpc = "¥" + (clicksBefore > 0 ? spendBefore.divide(new BigDecimal(clicksBefore), 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO);
			String acos = (sales1dBefore.compareTo(BigDecimal.ZERO) > 0 ? spendBefore.multiply(new BigDecimal(100)).divide(sales1dBefore, 0, BigDecimal.ROUND_HALF_UP) : 0) + "%";
			before = new DpggDto.DayDto(spend, sales1d, unitsSoldClicks1d, cpc, acos);
		}

		DpggDto.AddPercentDto addPercent = null;
		{
			BigDecimal spendPercent = spendBefore.compareTo(BigDecimal.ZERO) > 0 ? spendYesterday.subtract(spendBefore).multiply(new BigDecimal(100)).divide(spendBefore, 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String spend = spendPercent + (spendPercent.compareTo(BigDecimal.ZERO) > 0 ? "%↑" : "%↓");

			BigDecimal sales1dPercent = sales1dBefore.compareTo(BigDecimal.ZERO) > 0 ? sales1dYesterday.subtract(sales1dBefore).multiply(new BigDecimal(100)).divide(sales1dBefore, 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String sales1d = sales1dPercent + (sales1dPercent.compareTo(BigDecimal.ZERO) > 0 ? "%↑" : "%↓");

			BigDecimal unitsSoldClicks1dPercent = new BigDecimal(unitsSoldClicks1dBefore).compareTo(BigDecimal.ZERO) > 0 ? new BigDecimal(unitsSoldClicks1dYesterday - unitsSoldClicks1dBefore).multiply(new BigDecimal(100)).divide(new BigDecimal(unitsSoldClicks1dBefore), 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String unitsSoldClicks1d = unitsSoldClicks1dPercent + (unitsSoldClicks1dPercent.compareTo(BigDecimal.ZERO) > 0 ? "%↑" : "%↓");

			BigDecimal cpcYesterday = new BigDecimal(yesterday.getCpc().replace("¥", ""));
			BigDecimal cpcBefore = new BigDecimal(before.getCpc().replace("¥", ""));
			BigDecimal cpcPercent = cpcBefore.compareTo(BigDecimal.ZERO) > 0 ? cpcYesterday.subtract(cpcBefore).multiply(new BigDecimal(100)).divide(cpcBefore, 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String cpc = cpcPercent + (cpcPercent.compareTo(BigDecimal.ZERO) > 0 ? "%↑" : "%↓");

			BigDecimal acosYesterday = new BigDecimal(yesterday.getAcos().replace("%", ""));
			BigDecimal acosBefore = new BigDecimal(before.getAcos().replace("%", ""));
			BigDecimal acosPercent = acosBefore.compareTo(BigDecimal.ZERO) > 0 ? acosYesterday.subtract(acosBefore).multiply(new BigDecimal(100)).divide(acosBefore, 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String acos = acosPercent + (acosPercent.compareTo(BigDecimal.ZERO) > 0 ? "%↑" : "%↓");
			addPercent = new DpggDto.AddPercentDto(spend, sales1d, unitsSoldClicks1d, cpc, acos);
		}
		DpggDto dto = new DpggDto(finishTime, yesterday, before, addPercent);
		return R.ok(dto);
	}
	@Data
	@AllArgsConstructor
	private static class DpggDto{
		private String finishTime; // 更新截止时间
		private DayDto yesterday;
		private DayDto before;
		private AddPercentDto addPercent;

		@Data
		@AllArgsConstructor
		private static class DayDto{
			private String spend; // 广告花费
			private String sales1d; // 广告销售金额
			private Integer unitsSoldClicks1d; // 广告销售数量
			private String cpc; // CPC（广告花费/广告点击）
			private String acos; // ACOS(广告花费/广告销售金额)，百分比
		}

		@Data
		@AllArgsConstructor
		private static class AddPercentDto{
			private String spend; // 广告花费
			private String sales1d; // 广告销售金额
			private String unitsSoldClicks1d; // 广告销售数量
			private String cpc; // CPC（广告花费/广告点击）
			private String acos; // ACOS(广告花费/广告销售金额)，百分比
		}
	}

	/**
	 * 产品TOP
	 */
	@PostMapping("/topProduct")
	@ResponseBody
	public R topProduct(
			Integer type,
			Integer timeType,
			String region,
			String org,
			String company,
			String user,
			String shop){
		
		LoginUser loginUser = ShiroUtils.getLoginUser();

		String userId = loginUser.getUserId();
		Long roleId = loginUser.getRoleId();
		Integer authType = roleId.longValue() == 1L ? YsRoleMenuEnum.Type.ALL.value : sysMapper.getTypeOfRoleMenu(roleId, MENU_ID);

		List<Long> listShop = getListShop(shop);

		Date now = new Date();
		String dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -100));
		String dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		if (timeType == 1) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		} else if (timeType == 2) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -7));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		} else if (timeType == 3) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -30));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		} else if (timeType == 4) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -60));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -31));
		}
		String vSfJp = type == 1 ? "否" : "是";

		List<TopProductDto.RowDto> rows = new ArrayList<TopProductDto.RowDto>();
		List<Map<String, Object>> listMap = biMapper.topProduct(dayBegin, dayEnd, vSfJp, listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		int rank = 1;
		for(Map<String, Object> map : listMap) {
			String productCode = map.get("ProductCode").toString();
			String productName = map.get("ProductName").toString();
			String shopName = map.get("ShopName").toString();
			String fnsku = map.get("FnSku").toString();
			Integer numSale = Integer.parseInt(map.get("NumTotal").toString());
			BigDecimal amountSale = new BigDecimal(map.get("AmountRmbTotal").toString());
			rows.add(new TopProductDto.RowDto(rank, productCode, productName, shopName, fnsku, numSale, amountSale.toString()));
			rank++;
		}

		TopProductDto dto = new TopProductDto(rows);
		return R.ok(dto);
	}
	@Data
	@AllArgsConstructor
	private static class TopProductDto{
		private List<RowDto> rows;

		@Data
		@AllArgsConstructor
		private static class RowDto{
			private Integer rank;
			private String productCode; // 商品编码
			private String productName; // 商品名称
			private String shopName; // 店铺名称
			private String fnsku; // FNSKU
			private Integer numSale; // 销售数量
			private String amountSale; // 销售金额
		}
	}

	/**
	 * 店铺TOP
	 */
	@PostMapping("/topShop")
	@ResponseBody
	public R topShop(
			Integer timeType,
			String region,
			String org,
			String company,
			String user,
			String shop){
		
		LoginUser loginUser = ShiroUtils.getLoginUser();

		String userId = loginUser.getUserId();
		Long roleId = loginUser.getRoleId();
		Integer authType = roleId.longValue() == 1L ? YsRoleMenuEnum.Type.ALL.value : sysMapper.getTypeOfRoleMenu(roleId, MENU_ID);

		List<Long> listShop = getListShop(shop);

		Date now = new Date();
		String dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -100));
		String dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		if (timeType == 1) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		} else if (timeType == 2) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -7));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		} else if (timeType == 3) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -30));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		} else if (timeType == 4) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -60));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -31));
		}

		List<TopShopDto.RowDto> rows = new ArrayList<TopShopDto.RowDto>();
		List<Map<String, Object>> listMap = biMapper.topShop(dayBegin, dayEnd, listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt(),DateUtil.getYYYY_MM_DD(now));
		int rank = 1;
		for(Map<String, Object> map : listMap) {
			String shopName = map.get("ShopName").toString();
			String operateUserName = map.get("OperateUserName").toString();
			Integer numSale = Integer.parseInt(map.get("NumTotal").toString());
			BigDecimal amountSale = new BigDecimal(map.get("AmountRmbTotal").toString());
			int allRank = 0;
			if (timeType == 1) {
				allRank = Integer.parseInt(map.get("RankYesterday")!=null?map.get("RankYesterday").toString():"0");
			} else if (timeType == 2) {
				allRank = Integer.parseInt(map.get("RankSevenDay")!=null?map.get("RankSevenDay").toString():"0");
			} else if (timeType == 3) {
				allRank = Integer.parseInt(map.get("RankThirtyDay")!=null?map.get("RankThirtyDay").toString():"0");
			} else {
				allRank = Integer.parseInt(map.get("RankThirtyDayAgo")!=null?map.get("RankThirtyDayAgo").toString():"0");
			}
			rows.add(new TopShopDto.RowDto(rank, shopName, operateUserName, numSale, amountSale.toString(),allRank));
			rank++;
		}

		TopShopDto dto = new TopShopDto(rows);
		return R.ok(dto);
	}
	@Data
	@AllArgsConstructor
	private static class TopShopDto{
		private List<RowDto> rows;

		@Data
		@AllArgsConstructor
		private static class RowDto{
			private Integer rank;
			private String shopName; // 店铺名称
			private String operateUserName; // 运营人
			private Integer numSale; // 销售数量
			private String amountSale; // 销售金额
			private Integer allRank; // 总排名
		}
	}

	/**
	 * 精品广告TOP
	 */
	@PostMapping("/topProductAdvert")
	@ResponseBody
	public R topProductAdvert(
			Integer timeType,
			String region,
			String org,
			String company,
			String user,
			String shop){
		
		LoginUser loginUser = ShiroUtils.getLoginUser();

		String userId = loginUser.getUserId();
		Long roleId = loginUser.getRoleId();
		Integer authType = roleId.longValue() == 1L ? YsRoleMenuEnum.Type.ALL.value : sysMapper.getTypeOfRoleMenu(roleId, MENU_ID);

		List<Long> listShop = getListShop(shop);

		Date now = new Date();
		String dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -100));
		String dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		if (timeType == 1) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		} else if (timeType == 2) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -7));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		} else if (timeType == 3) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -30));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));
		} else if (timeType == 4) {
			dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -60));
			dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -31));
		}

		List<TopProductAdvertDto.RowDto> rows = new ArrayList<TopProductAdvertDto.RowDto>();
		List<Map<String, Object>> listMap = biMapper.topProductAdvert(dayBegin, dayEnd, listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		int rank = 1;
		for(Map<String, Object> map : listMap) {
			String productCode = map.get("ProductCode").toString();
			String productName = map.get("ProductName").toString();
			BigDecimal numSale = new BigDecimal(map.get("NumTotal").toString());
			BigDecimal numAdvert = new BigDecimal(map.get("UnitsSoldClicks1dTotal").toString());
			BigDecimal amountSale = new BigDecimal(map.get("AmountRmbTotal").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
			BigDecimal amountAdvert = new BigDecimal(map.get("SpendTotal").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
			BigDecimal clicks = new BigDecimal(map.get("ClicksTotal").toString());
			BigDecimal cpc = clicks.compareTo(BigDecimal.ZERO) > 0 ? amountAdvert.divide(clicks, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			BigDecimal acos = amountSale.compareTo(BigDecimal.ZERO) > 0 ? amountAdvert.divide(amountSale, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			BigDecimal numSaleAdvertProportion = numAdvert.compareTo(BigDecimal.ZERO) > 0 ? numAdvert.divide(numSale, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			rows.add(new TopProductAdvertDto.RowDto(rank, productCode, productName, numSale, numAdvert, amountSale, amountAdvert, cpc, acos,numSaleAdvertProportion));
			rank++;
		}

		TopProductAdvertDto dto = new TopProductAdvertDto(rows);
		return R.ok(dto);
	}
	@Data
	@AllArgsConstructor
	private static class TopProductAdvertDto{
		private List<RowDto> rows;

		@Data
		@AllArgsConstructor
		private static class RowDto{
			private Integer rank;
			private String productCode; // 商品编码
			private String productName; // 商品名称
			private BigDecimal numSale; // 销售数量
			private BigDecimal numAdvert; // 广告数量
			private BigDecimal amountSale; // 销售金额
			private BigDecimal amountAdvert; // 广告金额
			private BigDecimal cpc; // CPC
			private BigDecimal acos; // ACOS
			private BigDecimal numSaleAdvertProportion; // 广告占比（广告数量/销售数量）
		}
	}

	/**
	 * 业绩趋势
	 */
	@PostMapping("/yjqs")
	@ResponseBody
	public R yjqs(
			Integer type,
			String region,
			String org,
			String company,
			String user,
			String shop){
		
		LoginUser loginUser = ShiroUtils.getLoginUser();

		String userId = loginUser.getUserId();
		Long roleId = loginUser.getRoleId();
		Integer authType = roleId.longValue() == 1L ? YsRoleMenuEnum.Type.ALL.value : sysMapper.getTypeOfRoleMenu(roleId, MENU_ID);

		List<Long> listShop = getListShop(shop);

		Date now = new Date();
		String dayBegin = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -7));
		String dayEnd = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, -1));

		List<String> xdataArr = new ArrayList<String>();
		for (int i = -7; i < 0; i++) {
			String x = DateUtil.getYYYY_MM_DD(DateUtil.addDays(now, i)).substring(5);
			xdataArr.add(x);
		}

		YJQSDto.LegendDto legend = null;
		{
			List<String> data = new ArrayList<String>();
			if (type == 1) {
				data.add("销售金额");
				data.add("销售数量");
				data.add("销售单量");
				data.add("弃退单量");
			} else if (type == 2) {
				data.add("销售金额");
				data.add("广告销售金额");
				data.add("广告花费");
			} else if (type == 3) {
				data.add("广告销售数量");
				data.add("CPC");
				data.add("ACOS");
			}
			legend = new YJQSDto.LegendDto(data);
		}

		List<YJQSDto.SeriesDto> series = new ArrayList<YJQSDto.SeriesDto>();
		if (type == 1) {
			List<Map<String, Object>> listMap = biMapper.yjqsXsyjt(listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt(),dayBegin,dayEnd);
			{
				List<BigDecimal> data = new ArrayList<BigDecimal>();
				for (int i = 0; i < 7; i++) {
					BigDecimal value = BigDecimal.ZERO;
					if (listMap != null && listMap.size() > i) {
						Map<String, Object> map = listMap.get(i);
						value = new BigDecimal(map.get("AmountRmbTotal").toString());
					}
					data.add(value);
				}

				String name = "销售金额";
				String type2 = "line";
				Integer yAxisIndex = 0;
				series.add(new YJQSDto.SeriesDto(name, type2, yAxisIndex, data));
			}
			{
				List<BigDecimal> data = new ArrayList<BigDecimal>();
				for (int i = 0; i < 7; i++) {
					BigDecimal value = BigDecimal.ZERO;
					if (listMap != null && listMap.size() > i) {
						Map<String, Object> map = listMap.get(i);
						value = new BigDecimal(map.get("NumOrderTotal").toString());
					}
					data.add(value);
				}

				String name = "销售数量";
				String type2 = "line";
				Integer yAxisIndex = 1;
				series.add(new YJQSDto.SeriesDto(name, type2, yAxisIndex, data));
			}
			{
				List<BigDecimal> data = new ArrayList<BigDecimal>();
				for (int i = 0; i < 7; i++) {
					BigDecimal value = BigDecimal.ZERO;
					if (listMap != null && listMap.size() > i) {
						Map<String, Object> map = listMap.get(i);
						value = new BigDecimal(map.get("NumSaleTotal").toString());
					}
					data.add(value);
				}

				String name = "销售单量";
				String type2 = "line";
				Integer yAxisIndex = 1;
				series.add(new YJQSDto.SeriesDto(name, type2, yAxisIndex, data));
			}
			{
				List<BigDecimal> data = new ArrayList<BigDecimal>();
				for (int i = 0; i < 7; i++) {
					BigDecimal value = BigDecimal.ZERO;
					if (listMap != null && listMap.size() > i) {
						Map<String, Object> map = listMap.get(i);
						value = new BigDecimal(map.get("NumBackTotal").toString());
					}
					data.add(value);
				}

				String name = "弃退单量";
				String type2 = "line";
				Integer yAxisIndex = 1;
				series.add(new YJQSDto.SeriesDto(name, type2, yAxisIndex, data));
			}
		} else if (type == 2) {
			List<Map<String, Object>> listMap = biMapper.yjqsGgyjt(listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt(),dayBegin,dayEnd);
			List<Map<String, Object>> listMap2 = biMapper.yjqsXsyjt(listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt(),dayBegin,dayEnd);
			{
				List<BigDecimal> data = new ArrayList<BigDecimal>();
				for (int i = 0; i < 7; i++) {
					BigDecimal value = BigDecimal.ZERO;
					if (listMap2 != null && listMap2.size() > i) {
						Map<String, Object> map = listMap2.get(i);
						value = new BigDecimal(map.get("AmountRmbTotal").toString());
					}
					data.add(value);
				}

				String name = "销售金额";
				String type2 = "line";
				Integer yAxisIndex = 0;
				series.add(new YJQSDto.SeriesDto(name, type2, yAxisIndex, data));
			}
			{
				List<BigDecimal> data = new ArrayList<BigDecimal>();
				for (int i = 0; i < 7; i++) {
					BigDecimal value = BigDecimal.ZERO;
					if (listMap != null && listMap.size() > i) {
						Map<String, Object> map = listMap.get(i);
						value = new BigDecimal(map.get("Sales1dTotal").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
					}
					data.add(value);
				}

				String name = "广告销售金额";
				String type2 = "line";
				Integer yAxisIndex = 1;
				series.add(new YJQSDto.SeriesDto(name, type2, yAxisIndex, data));
			}
			{
				List<BigDecimal> data = new ArrayList<BigDecimal>();
				for (int i = 0; i < 7; i++) {
					BigDecimal value = BigDecimal.ZERO;
					if (listMap != null && listMap.size() > i) {
						Map<String, Object> map = listMap.get(i);
						value = new BigDecimal(map.get("SpendTotal").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
					}
					data.add(value);
				}

				String name = "广告花费";
				String type2 = "line";
				Integer yAxisIndex = 1;
				series.add(new YJQSDto.SeriesDto(name, type2, yAxisIndex, data));
			}
		} else if (type == 3) {
			List<Map<String, Object>> listMap = biMapper.yjqsGgxgt(listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt(),dayBegin,dayEnd);
//			List<Map<String, Object>> listMap2 = biMapper.yjqsGgyjt(); // 用于计算ACOS
			{
				List<BigDecimal> data = new ArrayList<BigDecimal>();
				for (int i = 0; i < 7; i++) {
					BigDecimal value = BigDecimal.ZERO;
					if (listMap != null && listMap.size() > i) {
						Map<String, Object> map = listMap.get(i);
						value = new BigDecimal(map.get("UnitsSoldClicks1dTotal").toString());
					}
					data.add(value);
				}

				String name = "广告销售数量";
				String type2 = "line";
				Integer yAxisIndex = 0;
				series.add(new YJQSDto.SeriesDto(name, type2, yAxisIndex, data));
			}
			{
				List<BigDecimal> data = new ArrayList<BigDecimal>();
				for (int i = 0; i < 7; i++) {
					BigDecimal value = BigDecimal.ZERO;
					if (listMap != null && listMap.size() > i) {
						Map<String, Object> map = listMap.get(i);
						BigDecimal clicksTotal = new BigDecimal(map.get("ClicksTotal").toString());
						BigDecimal spendTotal = new BigDecimal(map.get("SpendTotal").toString());
						value = clicksTotal.compareTo(BigDecimal.ZERO) > 0 ? spendTotal.divide(clicksTotal, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
					}
					data.add(value);
				}

				String name = "CPC";
				String type2 = "line";
				Integer yAxisIndex = 1;
				series.add(new YJQSDto.SeriesDto(name, type2, yAxisIndex, data));
			}
			{
				List<BigDecimal> data = new ArrayList<BigDecimal>();
				for (int i = 0; i < 7; i++) {
					BigDecimal value = BigDecimal.ZERO;
					if (listMap != null && listMap.size() > i) {
						Map<String, Object> map = listMap.get(i);
						BigDecimal Sales1d = new BigDecimal(map.get("Sales1dTotal").toString());
						value = Sales1d.compareTo(BigDecimal.ZERO) > 0 ? new BigDecimal(map.get("SpendTotal").toString()).divide(Sales1d, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
					}
					data.add(value);
				}

				String name = "ACOS";
				String type2 = "line";
				Integer yAxisIndex = 1;
				series.add(new YJQSDto.SeriesDto(name, type2, yAxisIndex, data));
			}
		}
		YJQSDto dto = new YJQSDto(xdataArr, legend, series);
		return R.ok(dto);
	}
	@Data
	@AllArgsConstructor
	private static class YJQSDto{
		private List<String> xdataArr; //X轴数组

		private LegendDto legend; // 标题线
		private List<SeriesDto> series;

		@Data
		@AllArgsConstructor
		private static class LegendDto{
			private List<String> data;
		}

		@Data
		@AllArgsConstructor
		private static class SeriesDto{
			private String name;
			private String type;
			private Integer yAxisIndex; // Y轴序号，0左，1右
			private List<BigDecimal> data;
		}
	}

	/**
	 * 库存状态
	 */
	@PostMapping("/kczt")
	@ResponseBody
	public R kczt(
			String region,
			String org,
			String company,
			String user,
			String shop){
		
		LoginUser loginUser = ShiroUtils.getLoginUser();

		String userId = loginUser.getUserId();
		Long roleId = loginUser.getRoleId();
		Integer authType = roleId.longValue() == 1L ? YsRoleMenuEnum.Type.ALL.value : sysMapper.getTypeOfRoleMenu(roleId, MENU_ID);

		System.out.println("---");
		List<Long> listShop = getListShop(shop);

//		KCZTDto.SeriesDto.ItemStyleDto.NormalDto normal = new KCZTDto.SeriesDto.ItemStyleDto.NormalDto(30);
		KCZTDto.SeriesDto.ItemStyleDto.NormalDto normal = null;

		List<KCZTDto.SeriesDto> series = new ArrayList<KCZTDto.SeriesDto>();

		BigDecimal numFuzhou = biMapper.sumStock("福州仓", listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		BigDecimal numUK = biMapper.sumStock("英国仓", listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		BigDecimal numUS = biMapper.sumStock("美国仓", listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		BigDecimal numHaiwai = numUK.add(numUS);
		BigDecimal numZaitu = biMapper.sumAmazonShopProductZT(listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		BigDecimal numZaishou = biMapper.sumAmazonShopProductZS(listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		BigDecimal numSaleLatest30 = biMapper.sumLatest30(listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		{
			BigDecimal value = numFuzhou;
			String color = "#51c7d7";
			KCZTDto.SeriesDto.ItemStyleDto itemStyle = new KCZTDto.SeriesDto.ItemStyleDto(color, normal);
			series.add(new KCZTDto.SeriesDto(value, itemStyle));
		}
		{
			BigDecimal value = numHaiwai;
			String color = "#f19b59";
			KCZTDto.SeriesDto.ItemStyleDto itemStyle = new KCZTDto.SeriesDto.ItemStyleDto(color, normal);
			series.add(new KCZTDto.SeriesDto(value, itemStyle));
		}
		{
			BigDecimal value = numZaitu;
			String color = "#ea707e";
			KCZTDto.SeriesDto.ItemStyleDto itemStyle = new KCZTDto.SeriesDto.ItemStyleDto(color, normal);
			series.add(new KCZTDto.SeriesDto(value, itemStyle));
		}
		{
			BigDecimal value = numZaishou;
			String color = "#7e9edb";
			KCZTDto.SeriesDto.ItemStyleDto itemStyle = new KCZTDto.SeriesDto.ItemStyleDto(color, normal);
			series.add(new KCZTDto.SeriesDto(value, itemStyle));
		}

		List<KCZTDto.RowDto> rows = new ArrayList<KCZTDto.RowDto>();
		{
			String name = "总库存";
			BigDecimal numStock = numFuzhou.add((numHaiwai!=null?numHaiwai:BigDecimal.ZERO)).add(numZaitu!=null?numZaitu:BigDecimal.ZERO).add(numZaishou!=null?numZaishou:BigDecimal.ZERO);
			BigDecimal numTimes = numSaleLatest30!=null && numSaleLatest30.compareTo(BigDecimal.ZERO) > 0 ? numStock.divide(numSaleLatest30, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String condition = numTimes.compareTo(new BigDecimal(4)) > 0 ? "偏高" : (numTimes.compareTo(BigDecimal.ONE) < 0 ? "偏低" : "");
			rows.add(new KCZTDto.RowDto(name, numStock, numTimes, condition));
		}
		{
			String name = "在售库存";
			BigDecimal numStock = numZaishou;
			BigDecimal numTimes =  numSaleLatest30!=null && numSaleLatest30.compareTo(BigDecimal.ZERO) > 0 ? numStock.divide(numSaleLatest30, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String condition = "";
			rows.add(new KCZTDto.RowDto(name, numStock, numTimes, condition));
		}
		{
			String name = "在途库存";
			BigDecimal numStock = numZaitu;
			BigDecimal numTimes =  numSaleLatest30!=null && numSaleLatest30.compareTo(BigDecimal.ZERO) > 0 ? numStock.divide(numSaleLatest30, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String condition = "";
			rows.add(new KCZTDto.RowDto(name, numStock, numTimes, condition));
		}
		{
			String name = "海外库存";
			BigDecimal numStock = numHaiwai;
			BigDecimal numTimes =  numSaleLatest30!=null && numSaleLatest30.compareTo(BigDecimal.ZERO) > 0 ? numStock.divide(numSaleLatest30, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String condition = "";
			rows.add(new KCZTDto.RowDto(name, numStock, numTimes, condition));
		}
		{
			String name = "国内库存";
			BigDecimal numStock = numFuzhou;
			BigDecimal numTimes =  numSaleLatest30!=null && numSaleLatest30.compareTo(BigDecimal.ZERO) > 0 ? numStock.divide(numSaleLatest30, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			String condition = "";
			rows.add(new KCZTDto.RowDto(name, numStock, numTimes, condition));
		}
		KCZTDto dto = new KCZTDto(series, rows, numSaleLatest30);
		return R.ok(dto);
	}
	@Data
	@AllArgsConstructor
	private static class KCZTDto{
		private List<SeriesDto> series;
		private List<RowDto> rows;
		private BigDecimal numSaleLatest30; // 近30天销量

		@Data
		@AllArgsConstructor
		private static class RowDto{
			private String name;
			private BigDecimal numStock; // 库存数量
			private BigDecimal numTimes; // 库存倍数
			private String condition; // 库存状况
		}

		@Data
		@AllArgsConstructor
		private static class SeriesDto{
			private BigDecimal value;
			private ItemStyleDto itemStyle;

			@Data
			@AllArgsConstructor
			private static class ItemStyleDto{
				private String color;
				private NormalDto normal;

				@Data
				@AllArgsConstructor
				private static class NormalDto{
					private Integer barWidth;
				}
			}
		}
	}

	/**
	 * 广告指标对比
	 */
	@PostMapping("/ggzbdb")
	@ResponseBody
	public R ggzbdb(
			String region,
			String org,
			String company,
			String user,
			String shop){
		
		LoginUser loginUser = ShiroUtils.getLoginUser();

		String userId = loginUser.getUserId();
		Long roleId = loginUser.getRoleId();
		Integer authType = roleId.longValue() == 1L ? YsRoleMenuEnum.Type.ALL.value : sysMapper.getTypeOfRoleMenu(roleId, MENU_ID);

		List<Long> listShop = getListShop(shop);

		Map<String, Object> mapLatest = biMapper.ggzbdbLatest(listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		Map<String, Object> mapBefore = biMapper.ggzbdbBefore(listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		BigDecimal spendLatest = new BigDecimal(mapLatest.get("SpendTotal").toString());
		BigDecimal spendBefore = new BigDecimal(mapBefore.get("SpendTotal").toString());
		BigDecimal amountSaleLatest = new BigDecimal(mapLatest.get("Sales1dTotal").toString());
		BigDecimal amountSaleBefore = new BigDecimal(mapBefore.get("Sales1dTotal").toString());
		BigDecimal clicksLatest = new BigDecimal(mapLatest.get("ClicksTotal").toString());
		BigDecimal clicksBefore = new BigDecimal(mapBefore.get("ClicksTotal").toString());
		List<GGZBDBDto.RowDto> rows = new ArrayList<GGZBDBDto.RowDto>();
		{
			String name = "广告花费";
			BigDecimal valueLatest = spendLatest.setScale(2, BigDecimal.ROUND_HALF_UP);
			BigDecimal valueBefore = spendBefore.setScale(2, BigDecimal.ROUND_HALF_UP);
			BigDecimal valueAll = valueLatest.add(valueBefore);
			BigDecimal percentLatest = valueAll.compareTo(BigDecimal.ZERO) > 0 ? valueLatest.multiply(new BigDecimal(100)).divide(valueAll, 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			BigDecimal percentBefore = new BigDecimal(100).subtract(percentLatest);
			Integer state = percentLatest.compareTo(percentBefore);
			rows.add(new GGZBDBDto.RowDto(name, valueLatest, valueBefore, percentLatest, percentBefore, state));
		}
		{
			String name = "广告销售额";
			BigDecimal valueLatest = amountSaleLatest.setScale(2, BigDecimal.ROUND_HALF_UP);
			BigDecimal valueBefore = amountSaleBefore.setScale(2, BigDecimal.ROUND_HALF_UP);
			BigDecimal valueAll = valueLatest.add(valueBefore);
			BigDecimal percentLatest = valueAll.compareTo(BigDecimal.ZERO) > 0 ? valueLatest.multiply(new BigDecimal(100)).divide(valueAll, 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			BigDecimal percentBefore = new BigDecimal(100).subtract(percentLatest);
			Integer state = percentLatest.compareTo(percentBefore);
			rows.add(new GGZBDBDto.RowDto(name, valueLatest, valueBefore, percentLatest, percentBefore, state));
		}
		{
			String name = "广告销售数量";
			BigDecimal valueLatest = new BigDecimal(mapLatest.get("UnitsSoldClicks1dTotal").toString());
			BigDecimal valueBefore = new BigDecimal(mapBefore.get("UnitsSoldClicks1dTotal").toString());
			BigDecimal valueAll = valueLatest.add(valueBefore);
			BigDecimal percentLatest = valueAll.compareTo(BigDecimal.ZERO) > 0 ? valueLatest.multiply(new BigDecimal(100)).divide(valueAll, 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			BigDecimal percentBefore = new BigDecimal(100).subtract(percentLatest);
			Integer state = percentLatest.compareTo(percentBefore);
			rows.add(new GGZBDBDto.RowDto(name, valueLatest, valueBefore, percentLatest, percentBefore, state));
		}
		{
			String name = "点击量";
			BigDecimal valueLatest = new BigDecimal(mapLatest.get("ClicksTotal").toString());
			BigDecimal valueBefore = new BigDecimal(mapBefore.get("ClicksTotal").toString());
			BigDecimal valueAll = valueLatest.add(valueBefore);
			BigDecimal percentLatest = valueAll.compareTo(BigDecimal.ZERO) > 0 ? valueLatest.multiply(new BigDecimal(100)).divide(valueAll, 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			BigDecimal percentBefore = new BigDecimal(100).subtract(percentLatest);
			Integer state = percentLatest.compareTo(percentBefore);
			rows.add(new GGZBDBDto.RowDto(name, valueLatest, valueBefore, percentLatest, percentBefore, state));
		}
		{
			String name = "ACOS";
			BigDecimal valueLatest = amountSaleLatest.compareTo(BigDecimal.ZERO) > 0 ? spendLatest.divide(amountSaleLatest, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			BigDecimal valueBefore = amountSaleBefore.compareTo(BigDecimal.ZERO) > 0 ? spendBefore.divide(amountSaleBefore, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			BigDecimal valueAll = valueLatest.add(valueBefore);
			BigDecimal percentLatest = valueAll.compareTo(BigDecimal.ZERO) > 0 ? valueLatest.multiply(new BigDecimal(100)).divide(valueAll, 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			BigDecimal percentBefore = new BigDecimal(100).subtract(percentLatest);
			Integer state = percentBefore.compareTo(percentLatest);
			rows.add(new GGZBDBDto.RowDto(name, valueLatest, valueBefore, percentLatest, percentBefore, state));
		}
		{
			String name = "CPC";
			BigDecimal valueLatest = clicksLatest.compareTo(BigDecimal.ZERO) > 0 ? spendLatest.divide(clicksLatest, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			BigDecimal valueBefore = clicksBefore.compareTo(BigDecimal.ZERO) > 0 ? spendBefore.divide(clicksBefore, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			BigDecimal valueAll = valueLatest.add(valueBefore);
			BigDecimal percentLatest = valueAll.compareTo(BigDecimal.ZERO) > 0 ? valueLatest.multiply(new BigDecimal(100)).divide(valueAll, 0, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
			BigDecimal percentBefore = new BigDecimal(100).subtract(percentLatest);
			Integer state = percentBefore.compareTo(percentLatest);
			rows.add(new GGZBDBDto.RowDto(name, valueLatest, valueBefore, percentLatest, percentBefore, state));
		}
		GGZBDBDto dto = new GGZBDBDto(rows);
		return R.ok(dto);
	}
	@Data
	@AllArgsConstructor
	private static class GGZBDBDto{
		private List<RowDto> rows;

		@Data
		@AllArgsConstructor
		public static class RowDto{
			private String name;
			private BigDecimal valueLatest;
			private BigDecimal valueBefore;
			private BigDecimal percentLatest;
			private BigDecimal percentBefore;
			private Integer state; // -1小于一半0等于一半1大于一半
		}
	}

	/**
	 * 广告沙漏
	 */
	@PostMapping("/ggsl")
	@ResponseBody
	public R ggsl(
			String region,
			String org,
			String company,
			String user,
			String shop){
		
		LoginUser loginUser = ShiroUtils.getLoginUser();

		String userId = loginUser.getUserId();
		Long roleId = loginUser.getRoleId();
		Integer authType = roleId.longValue() == 1L ? YsRoleMenuEnum.Type.ALL.value : sysMapper.getTypeOfRoleMenu(roleId, MENU_ID);

		List<Long> listShop = getListShop(shop);

		Map<String, Object> mapLatest = biMapper.ggslLatest7(listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		List<GGSLDto.RowDto> rows1 = new ArrayList<GGSLDto.RowDto>();
		{
			String name = "点击";
			BigDecimal value = new BigDecimal(mapLatest.get("ClicksTotal").toString());
			GGSLDto.RowDto.ItemStyleDto itemStyle = new GGSLDto.RowDto.ItemStyleDto("#e7668a");
			rows1.add(new GGSLDto.RowDto(name, value, itemStyle));
		}
		{
			String name = "销售订单";
			BigDecimal value = new BigDecimal(mapLatest.get("UnitsSoldClicks1dTotal").toString());
			GGSLDto.RowDto.ItemStyleDto itemStyle = new GGSLDto.RowDto.ItemStyleDto("#f2a36d");
			rows1.add(new GGSLDto.RowDto(name, value, itemStyle));
		}
		{
			String name = "花费";
			BigDecimal value = new BigDecimal(mapLatest.get("SpendTotal").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
			GGSLDto.RowDto.ItemStyleDto itemStyle = new GGSLDto.RowDto.ItemStyleDto("#7a84e4");
			rows1.add(new GGSLDto.RowDto(name, value, itemStyle));
		}
		{
			String name = "销售金额";
			BigDecimal value = new BigDecimal(mapLatest.get("Sales1dTotal").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
			GGSLDto.RowDto.ItemStyleDto itemStyle = new GGSLDto.RowDto.ItemStyleDto("#68d2a4");
			rows1.add(new GGSLDto.RowDto(name, value, itemStyle));
		}

		Map<String, Object> mapBefore = biMapper.ggslBefore7(listShop, authType, userId, loginUser.getOperateOrgNodeLft(), loginUser.getOperateOrgNodeRgt());
		List<GGSLDto.RowDto> rows2 = new ArrayList<GGSLDto.RowDto>();
		{
			String name = "点击";
			BigDecimal value = new BigDecimal(mapBefore.get("ClicksTotal").toString());
			GGSLDto.RowDto.ItemStyleDto itemStyle = new GGSLDto.RowDto.ItemStyleDto("#e7668a");
			rows2.add(new GGSLDto.RowDto(name, value, itemStyle));
		}
		{
			String name = "销售订单";
			BigDecimal value = new BigDecimal(mapBefore.get("UnitsSoldClicks1dTotal").toString());
			GGSLDto.RowDto.ItemStyleDto itemStyle = new GGSLDto.RowDto.ItemStyleDto("#f2a36d");
			rows2.add(new GGSLDto.RowDto(name, value, itemStyle));
		}
		{
			String name = "花费";
			BigDecimal value = new BigDecimal(mapBefore.get("SpendTotal").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
			GGSLDto.RowDto.ItemStyleDto itemStyle = new GGSLDto.RowDto.ItemStyleDto("#7a84e4");
			rows2.add(new GGSLDto.RowDto(name, value, itemStyle));
		}
		{
			String name = "销售金额";
			BigDecimal value = new BigDecimal(mapBefore.get("Sales1dTotal").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
			GGSLDto.RowDto.ItemStyleDto itemStyle = new GGSLDto.RowDto.ItemStyleDto("#68d2a4");
			rows2.add(new GGSLDto.RowDto(name, value, itemStyle));
		}
		GGSLDto dto = new GGSLDto(rows1, rows2);
		return R.ok(dto);
	}
	@Data
	@AllArgsConstructor
	private static class GGSLDto{
		private List<RowDto> rows1;
		private List<RowDto> rows2;

		@Data
		@AllArgsConstructor
		private static class RowDto{
			private String name;
			private BigDecimal value;
			private ItemStyleDto itemStyle;

			@Data
			@AllArgsConstructor
			private static class ItemStyleDto{
				private String color;
			}
		}
	}

	public static List<Long> getListShop(String shop) {
		List<Long> listShop = new ArrayList<Long>();
		if (shop != null && shop.length() > 0) {
			JSONArray shopJA = JSON.parseArray(shop);
			for (int i = 0; i < shopJA.size(); i++) {
				JSONObject shopJO = shopJA.getJSONObject(i);
				listShop.add(shopJO.getLong("value"));
			}
		}
		return listShop;
	}
}
